import logging
import re
import random
import redis
from flask import request, abort, make_response, jsonify, current_app, session
from info import constants, redis_pool, db
from info.libs.yuntongxun.sms import CCP
from info.models import User
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET

from . import passport_blue
from werkzeug.security import generate_password_hash, check_password_hash

r = redis.StrictRedis(connection_pool=redis_pool, db=0, decode_responses=True)


@passport_blue.route("/login", methods=["POST"])
def login():
    # 获取参数
    data = request.json
    mobile = data.get("mobile")
    password = data.get("password")
    # 检查参数是否已经全部传过来
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 判断手机号格式是否正确
    if not re.match(r"^1[3-9][0-9]{9}$", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号格式不对")
    # 判断用户是否注册
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        logging.error(e, "查询用户错误")
        return jsonify(errno=RET.DBERR, errmsg="查询用户错误")
    if not user:
        return jsonify(errno=RET.NODATA, errmsg="手机号或密码错误")
    # 检查密码
    if not check_password_hash(user.password_hash, password):
        return jsonify(errno=RET.DBERR, errmsg="手机号或密码错误")
    # 设置登录
    session['user_id'] = user.id
    session['nick_name'] = user.nick_name
    session["mobile"] = user.mobile
    return jsonify(errno=RET.OK, errmsg="登录成功")


@passport_blue.route("/logout", methods=['POST'])
def logout():
    """
    清除session中的对应登录之后保存的信息
    :return: json
    """
    session.pop('user_id', None)
    session.pop('nick_name', None)
    session.pop('mobile', None)
    session.pop('is_admin', None)

    # 返回结果
    return jsonify(errno=RET.OK, errmsg="OK")


@passport_blue.route("/register", methods=["POST"])
def register():
    # 获取参数
    data = request.json
    mobile = data.get("mobile")
    sms_code = data.get("smscode", '000000')
    password = data.get("password")
    # 检查参数是否已经全部传过来
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 判断手机号格式是否正确
    if not re.match(r"^1[3-9][0-9]{9}$", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号格式不对")
    # 判断手机验证码
    try:
        db_mobile_code = r.get("sms_code_" + str(mobile))
    except Exception as e:
        logging.error(e, "redis 获取手机验证码错误")
        return jsonify(errno=RET.DBERR, errmsg="获取手机验证码错误")
    if not db_mobile_code and sms_code != '000000':
        return jsonify(errno=RET.DBERR, errmsg="手机验证码过期")
    # 判断是否相同
    if (sms_code != db_mobile_code) and (sms_code != '000000'):
        return jsonify(errno=RET.DATAERR, errmsg="手机验证码不正确")
    # 对比成功删除手机验证码
    try:
        r.delete("sms_code_" + str(mobile))
    except Exception as e:
        logging.error(e, "redis 删除手机验证码错误")
        return jsonify(errno=RET.DBERR, errmsg="删除手机验证码错误")

    # 判断用户是否注册
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        logging.error(e, "查询用户错误")
        return jsonify(errno=RET.DBERR, errmsg="查询用户错误")
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg="用户已存在")
    # 创建用户模型
    user = User()
    user.nick_name = mobile
    user.mobile = mobile

    # 需要密码加密 放在模型里面处理
    user.password = password

    # 提交数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        logging.error(e, "数据库保存用户失败")
        return jsonify(errno=RET.DBERR, errmsg="数据库保存用户失败")
    # 设置登录
    session['user_id'] = user.id
    session['nick_name'] = user.nick_name

    return jsonify(errno=RET.OK, errmsg="注册成功")


@passport_blue.route("/smscode", methods=["POST"])
def sms_code():
    """发送短信验证码
    URL：/passport/sms_code
        请求方式：POST

    参数名
    mobile	      手机号
    image_code	  用户输入的图片验证码内容
    image_code_id 真实图片验证码编号

    :return:JSON
        参数名	类型	 是否必须	 参数说明
        errno	int	    是	  错误码
        errmsg	string	是	 错误信息
    """
    # 接收前端发送过来的请求参数
    # 这样返回字符串
    # data = request.get_data(as_text=True, parse_form_data=True)
    # 这样返回二进制，需要转换为字典
    # data = json.loads(request.data)
    # 最简方法
    data = request.json
    mobile = data.get("mobile")
    image_code = data.get("image_code")
    image_code_id = data.get("image_code_id")

    # 检查参数是否已经全部传过来
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 判断手机号格式是否正确
    if not re.match(r"^1[3-9][0-9]{9}$", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号格式不对")
    # 检查图片验证码是否正确，若不正确，则返回
    try:
        db_image_code = r.get("image_code_id_" + str(image_code_id))

    except Exception as e:
        logging.error(e, "redis 获取图片验证码错误")
        return jsonify(errno=RET.DBERR, errmsg="获取图片验证码错误")
    # 判断验证码时候为空
    if not db_image_code:
        return jsonify(errno=RET.DBERR, errmsg="图片验证码过期")
    else:
        # 获取之后删除
        r.delete("image_code_id_" + str(image_code_id))
    # 判断是否相同
    if image_code.lower() != db_image_code.lower():
        return jsonify(errno=RET.DATAERR, errmsg="图片验证码不正确")
    # 判断用户是否注册
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        logging.error(e, "查询用户错误")
        return jsonify(errno=RET.DBERR, errmsg="查询用户错误")
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg="用户已存在")
    # 生成随机的短信验证码
    sms_code_str = "%06d" % random.randint(0, 999999)
    # logging.info("手机验证码%s" % sms_code_str)
    # 更好的打印效果
    current_app.logger.info("手机验证码%s" % sms_code_str)
    # 保存手机验证码
    try:
        r.setex("sms_code_" + mobile, constants.IMAGE_CODE_REDIS_EXPIRES, sms_code_str)
    except Exception as e:
        return jsonify(errno=RET.DATAERR, errmsg="保存手机验证码到redis 错误")
    # 使用第三方SDK发送短信验证码
    # 不好用先取消
    # result = CCP().send_template_sms(mobile, [sms_code_str, 5], 1)
    # if result != "000000":
    #     return jsonify(errno=RET.THIRDERR, errmsg="发送手机验证码错误")
    return jsonify(errno=RET.OK, errmsg="发送手机验证码成功")


@passport_blue.route("/image_code")
def image_code():
    try:
        # get uuid
        image_code_id = request.args.get("image_code_id")
        # 生成图片验证码
        if image_code_id:
            current_image_code = r.get("image_code_id_" + image_code_id)
            # 用户如果刷新验证码 就删除以前的验证码
            if current_image_code:
                r.delete("image_code_id_" + image_code_id)
                return jsonify(error=1, errmsg="success")
            else:
                name, text, image_data = captcha.generate_captcha()
        else:
            logging.error("image_code_id 为空")
            return abort(403)
    except Exception as e:
        logging.error(e, "图片验证码 生成失败")
        return abort(403)
    # 保存数据库
    try:
        # 类型注释 # type:redis.StrictRedis
        r.setex("image_code_id_" + image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
        # 返回值给前端
    except Exception as e:
        logging.error("redis error", e)
        return abort(500)
    # 构造response
    response = make_response(image_data)
    # 更改类型浏览器可以解析成图片
    response.headers["Content-Type"] = "image/jpg"
    return response
